﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ПрограммныйИнтерфейс

// Дополнительные настройки отчета по умолчанию, определяющие:
//  * Признак формирования отчета при открытии;
//  * Подключаемые обработчики событий;
//  * Настройки печати;
//  * Использование функции расчетных показателей;
//  * Права.
//
// Возвращаемое значение:
//   Структура - настройки (дополнительные свойства) отчета, хранящиеся в данных формы:
//       
//       * ФормироватьСразу - Булево - значение по умолчанию для флажка "Формировать сразу".
//           Когда флажок включен, то отчет будет формироваться после открытия,
//           после выбора пользовательских настроек, после выбора другого варианта отчета.
//       
//       * ВыводитьСуммуВыделенныхЯчеек - Булево - если Истина, то в отчете будет выводиться поле автосуммы.
//       
//       * РазрешеноИзменятьСтруктуру - Булево - если Ложь, то в настройках отчета будет скрыта вкладка "Структура".
//           Если Истина, то вкладка "Структура" показывается для отчетов на СКД: в расширенном режиме,
//           а также в простом режиме, если в пользовательские настройки выведены флажки использования группировок.
//       
//       * РазрешеноИзменятьВарианты - Булево - если Ложь, то блокируются кнопки изменения вариантов этого отчета. 
//           Если у текущего пользователя нет прав "СохранениеДанныхПользователя" и "Добавление" 
//           справочника ВариантыОтчетов, то принудительно устанавливается в Ложь.
//
//       * РазрешеноВыбиратьИНастраиватьВариантыБезСохранения - Булево - если Истина,
//           то есть возможность выбора и настройки предопределенных вариантов отчета, но без возможности сохранения 
//           выполненных настроек. Например, может быть задано для контекстных отчетов (открываемых с параметрами), 
//           у которых есть несколько вариантов.
//
//       * ПараметрыРасположенияЭлементовУправления - Структура
//                                                  - Неопределено - варианты:
//           - Неопределено - параметры элементов управления общей формы отчетов "по умолчанию".
//           - Структура - с именами настройки в коллекции НастройкиКомпоновкиДанных свойства Настройки
//                         типа КомпоновщикНастроекКомпоновкиДанных:
//               ** Отбор           - Массив - как у следующего свойства.
//               ** ПараметрыДанных - Структура - со свойствами поля формы:
//                    *** Поле                     - Строка - имя поля, отображение которого настраивается.
//                    *** РастягиватьПоГоризонтали - Булево - значение свойства поля формы.
//                    *** АвтоМаксимальнаяШирина   - Булево - значение свойства поля формы.
//                    *** Ширина                   - Число  - значение свойства поля формы.
//
//            Пример определения описываемого параметра:
//
//               МассивНастроек              = Новый Массив;
//               НастройкиЭлементаУправления = Новый Структура;
//               НастройкиЭлементаУправления.Вставить("Поле",                     "СписокРегистров");
//               НастройкиЭлементаУправления.Вставить("РастягиватьПоГоризонтали", Ложь);
//               НастройкиЭлементаУправления.Вставить("АвтоМаксимальнаяШирина",   Истина);
//               НастройкиЭлементаУправления.Вставить("Ширина",                   40);
//
//               МассивНастроек.Добавить(НастройкиЭлементаУправления);
//
//               НастройкиЭлементовУправления = Новый Структура();
//               НастройкиЭлементовУправления.Вставить("ПараметрыДанных", МассивНастроек);
//
//               Возврат НастройкиЭлементовУправления;
//
//       * ЗагрузитьНастройкиПриИзмененииПараметров - Массив - коллекция параметров компоновки данных,
//                                                    изменение которых, приводит к переформированию
//                                                    Схемы компоновки данных.
//
//               // Пример:
//               // 1. Инициализация:
//               //	Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт
//               //		Настройки.ЗагрузитьНастройкиПриИзмененииПараметров = Отчеты.УниверсальныйОтчет.ЗагрузитьНастройкиПриИзмененииПараметров();
//               //	КонецПроцедуры
//
//               //	Функция ЗагрузитьНастройкиПриИзмененииПараметров() Экспорт 
//               //		Параметры = Новый Массив;
//               //		Параметры.Добавить(Новый ПараметрКомпоновкиДанных("ТипОбъектаМетаданных"));
//               //		Параметры.Добавить(Новый ПараметрКомпоновкиДанных("ИмяОбъектаМетаданных"));
//               //		Параметры.Добавить(Новый ПараметрКомпоновкиДанных("ИмяТаблицы"));
//               //		
//               //		Возврат Параметры;
//               //	КонецФункции
//
//               // 2. Использование:
//               //	Процедура Подключаемый_ЭлементНастройки_ПриИзменении(Элемент)
//               //		...
//               //		Если ТипЗнч(ЭлементПользовательскойНастройки) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных")
//               //			И НастройкиОтчета.ЗагрузитьНастройкиПриИзмененииПараметров.Найти(ЭлементПользовательскойНастройки.Параметр) <> Неопределено Тогда 
//               //			// Вызов метода переформирования Схемы компоновки данных...
//               //		КонецЕсли;
//
//       * ПоляПоиска - Массив из Строка - коллекция имен полей компоновки данных, которые участвуют в универсальном поиске.
//       * ВариантПредставленияПериода - ПеречислениеСсылка.ВариантыПредставленияПериода - определяет вариант
//           представления периода на форме отчета.
//       * ВариантПериода - ПеречислениеСсылка.ВариантыПериода - определяет вариант формы выбора периода.
//       * ОтключитьСтандартноеКонтекстноеМеню - Булево - признак, позволяющий выключить использование
//           контекстного меню и настройки колонки отчета.
//       * СкрытьКомандыРассылки - Булево - флаг, позволяющий скрыть команды рассылок, у тех отчетов,
//           для которых рассылка не имеет смысла.
//       * Печать - Структура - параметры печати табличного документа "по умолчанию":
//           ** ПолеСверху - Число - отступ сверху при печати (в миллиметрах).
//           ** ПолеСлева  - Число - отступ слева  при печати (в миллиметрах).
//           ** ПолеСнизу  - Число - отступ снизу  при печати (в миллиметрах).
//           ** ПолеСправа - Число - отступ справа при печати (в миллиметрах).
//           ** ОриентацияСтраницы - ориентацияСтраницы - "Портрет" или "Ландшафт".
//           ** АвтоМасштаб - Булево - автоматически подгонять масштаб под размер страницы.
//           ** МасштабПечати - Число - масштаб изображения (в процентах).
//       * События - Структура - события, для которых определены обработчики в модуле объекта отчета:
//           ** ПриСозданииНаСервере - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // См. ОтчетыПереопределяемый.ПриСозданииНаСервере.
//               Процедура ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПередЗагрузкойНастроекВКомпоновщик - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   Контекст - Произвольный
//               //   КлючСхемы - Строка
//               //   КлючВарианта - Строка, Неопределено
//               //   НовыеНастройкиКД - НастройкиКомпоновкиДанных, Неопределено
//               //   НовыеПользовательскиеНастройкиКД - ПользовательскиеНастройкиКомпоновкиДанных, Неопределено
//               //
//               Процедура ПередЗагрузкойНастроекВКомпоновщик(Контекст, КлючСхемы, КлючВарианта, НовыеНастройкиКД, НовыеПользовательскиеНастройкиКД) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПослеЗагрузкиНастроекВКомпоновщик - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               //  Параметры:
//               //    ДополнительныеПараметры - Структура
//               //
//               Процедура ПослеЗагрузкиНастроекВКомпоновщик(ДополнительныеПараметры) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПередЗагрузкойВариантаНаСервере - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // См. ОтчетыПереопределяемый.ПередЗагрузкойВариантаНаСервере.
//               Процедура ПередЗагрузкойВариантаНаСервере(Форма, НовыеНастройкиКД) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПриЗагрузкеВариантаНаСервере - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   Форма - ФормаКлиентскогоПриложения
//               //         - РасширениеУправляемойФормыДляОтчета:
//               //            * Отчет - ДанныеФормыСтруктура
//               //                    - ОтчетОбъект
//               //   НовыеНастройкиКД - НастройкиКомпоновкиДанных
//               //
//               Процедура ПриЗагрузкеВариантаНаСервере(Форма, НовыеНастройкиКД) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПриЗагрузкеПользовательскихНастроекНаСервере - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   Форма - ФормаКлиентскогоПриложения
//               //   НовыеПользовательскиеНастройкиКД - ПользовательскиеНастройкиКомпоновкиДанных
//               //
//               Процедура ПриЗагрузкеПользовательскихНастроекНаСервере(Форма, НовыеПользовательскиеНастройкиКД) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПередЗаполнениемПанелиБыстрыхНастроек - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   Форма - ФормаКлиентскогоПриложения
//               //   ПараметрыЗаполнения - Структура
//               //
//               Процедура ПередЗаполнениемПанелиБыстрыхНастроек(Форма, ПараметрыЗаполнения) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПослеЗаполненияПанелиБыстрыхНастроек - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   Форма - ФормаКлиентскогоПриложения
//               //   ПараметрыЗаполнения - Структура
//               //
//               Процедура ПослеЗаполненияПанелиБыстрыхНастроек(Форма, ПараметрыЗаполнения) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПриОпределенииПараметровВыбора - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // См. ОтчетыПереопределяемый.ПриОпределенииПараметровВыбора.
//               Процедура ПриОпределенииПараметровВыбора(Форма, СвойстваНастройки) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПриОпределенииИспользуемыхТаблиц - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   КлючВарианта - Строка, Неопределено
//               //   ИспользуемыеТаблицы - Массив из Строка
//               //
//               Процедура ПриОпределенииИспользуемыхТаблиц(КлючВарианта, ИспользуемыеТаблицы) Экспорт
//               	
//               КонецПроцедуры
//           
//           ** ПриОпределенииОсновныхПолей - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // См. ОтчетыПереопределяемый.ПриОпределенииОсновныхПолей.
//               Процедура ПриОпределенииОсновныхПолей(Форма, ОсновныеПоля) Экспорт 
//               	
//               КонецПроцедуры
//           
//           ** ПередФормированиемОтчета - Булево - если Истина, то в модуле объекта отчета
//               следует определить обработчик события по шаблону:
//               
//               // Параметры:
//               //   ФормаОтчета - ФормаКлиентскогоПриложения
//               //   ДополнительныеПараметры - Структура:
//               //     * ТекстПредупреждения - Строка
//               //     * ИмяПараметраХраненияОтказаОтПредупреждения - Строка
//               //
//               Процедура Процедура ПередФормированиемОтчета(ФормаОтчета, ДополнительныеПараметры) Экспорт
//               	
//               КонецПроцедуры
//
Функция НастройкиОтчетаПоУмолчанию() Экспорт
	Настройки = Новый Структура;
	Настройки.Вставить("ФормироватьСразу", Ложь);
	Настройки.Вставить("ВыводитьСуммуВыделенныхЯчеек", Истина);
	Настройки.Вставить("РазрешеноИзменятьСтруктуру", Истина);
	Настройки.Вставить("РазрешеноИзменятьВарианты", Истина);
	Настройки.Вставить("РазрешеноВыбиратьИНастраиватьВариантыБезСохранения", Ложь);
	Настройки.Вставить("ПараметрыРасположенияЭлементовУправления", Неопределено);
	Настройки.Вставить("СкрытьКомандыРассылки", Ложь);
	Настройки.Вставить("РазрешеноЗагружатьСхему", Ложь);
	Настройки.Вставить("РазрешеноРедактироватьСхему", Ложь);
	Настройки.Вставить("РазрешеноВосстанавливатьСтандартнуюСхему", Ложь);
	Настройки.Вставить("ЗагрузитьНастройкиПриИзмененииПараметров", Новый Массив);
	Настройки.Вставить("ПоляПоиска", Новый Массив);
	Настройки.Вставить("ВариантПредставленияПериода", ПредопределенноеЗначение("Перечисление.ВариантыПредставленияПериода.Стандартный"));
	Настройки.Вставить("ВариантПериода", ПредопределенноеЗначение("Перечисление.ВариантыПериода.Стандартный"));
	Настройки.Вставить("ОтключитьСтандартноеКонтекстноеМеню", Ложь);
	
	Печать = Новый Структура;
	Печать.Вставить("ПолеСверху", 10);
	Печать.Вставить("ПолеСлева", 10);
	Печать.Вставить("ПолеСнизу", 10);
	Печать.Вставить("ПолеСправа", 10);
	Печать.Вставить("ОриентацияСтраницы", ОриентацияСтраницы.Портрет);
	Печать.Вставить("АвтоМасштаб", Истина);
	Печать.Вставить("МасштабПечати", Неопределено);
	
	Настройки.Вставить("Печать", Печать);
	
	События = Новый Структура;
	События.Вставить("ПриСозданииНаСервере", Ложь);
	События.Вставить("ПередЗагрузкойНастроекВКомпоновщик", Ложь);
	События.Вставить("ПослеЗагрузкиНастроекВКомпоновщик", Ложь);
	События.Вставить("ПередЗагрузкойВариантаНаСервере", Ложь);
	События.Вставить("ПриЗагрузкеВариантаНаСервере", Ложь);
	События.Вставить("ПриЗагрузкеПользовательскихНастроекНаСервере", Ложь);
	События.Вставить("ПередЗаполнениемПанелиБыстрыхНастроек", Ложь);
	События.Вставить("ПослеЗаполненияПанелиБыстрыхНастроек", Ложь);
	События.Вставить("ПриОпределенииПараметровВыбора", Ложь);
	События.Вставить("ПриОпределенииИспользуемыхТаблиц", Ложь);
	События.Вставить("ПриОпределенииСвойствЭлементовФормыНастроек", Ложь);
	События.Вставить("ПриОпределенииОсновныхПолей", Ложь);
	События.Вставить("ПередФормированиемОтчета", Ложь);
	
	Настройки.Вставить("События", События);
	
	Возврат Настройки;
КонецФункции

#Область УстаревшиеПроцедурыИФункции

// Устарела. Следует использовать ОтчетыКлиентСервер.НастройкиОтчетаПоУмолчанию.
// Настройки формы отчета по умолчанию.
//
// Возвращаемое значение:
//   Структура:
//
Функция ПолучитьНастройкиОтчетаПоУмолчанию() Экспорт
	Возврат НастройкиОтчетаПоУмолчанию();
КонецФункции

#КонецОбласти

#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

// Возвращаемое значение:
//  Строка
//
Функция ПрефиксИмениКомандыСПредварительнымСохранениемВариантаОтчета() Экспорт
	
	Возврат "СохранитьВариант" + "_";
	
КонецФункции

// Находит параметр в настройках компоновки по его имени.
// Если пользовательская настройка не существует (например, если параметр не выведен в пользовательские настройки),
// то ищет значение параметра в настройках варианта.
//
// Параметры:
//   НастройкиКД - НастройкиКомпоновкиДанных
//               - Неопределено -
//       Настройки варианта отчета, в которых будет осуществляться вторая итерация поиска значения.
//   ПользовательскиеНастройкиКД - ПользовательскиеНастройкиКомпоновкиДанных
//                               - Неопределено -
//       Пользовательские настройки, в которых будет осуществляться первая итерация поиска значения.
//   ИмяПараметра - Строка - имя параметра. Должно удовлетворять требованиям образования имен переменных.
//
// Возвращаемое значение:
//   Структура - найденные значения параметров:
//       Ключ - имя параметра;
//       Значение - значение параметра. Неопределено, если параметр не существует.
//
Функция НайтиПараметр(НастройкиКД, ПользовательскиеНастройкиКД, ИмяПараметра) Экспорт
	Возврат НайтиПараметры(НастройкиКД, ПользовательскиеНастройкиКД, ИмяПараметра)[ИмяПараметра];
КонецФункции

// Находит общую настройку по идентификатору пользовательской настройки.
//
// Параметры:
//   Настройки - НастройкиКомпоновкиДанных - коллекции настроек.
//   Идентификатор - Строка - идентификатор пользовательской настройки.
//   Иерархия - Массив - коллекция настроек структуры компоновки данных.
//   ПользовательскиеНастройки - ПользовательскиеНастройкиКомпоновкиДанных - коллекция пользовательских настроек.
//
Функция ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки, Идентификатор, Иерархия = Неопределено, ПользовательскиеНастройки = Неопределено) Экспорт
	Если Иерархия = Неопределено
		И ТипЗнч(ПользовательскиеНастройки) = Тип("ПользовательскиеНастройкиКомпоновкиДанных") Тогда 
		
		НайденныеЭлементы =
			ПользовательскиеНастройки.ПолучитьОсновныеНастройкиПоИдентификаторуПользовательскойНастройки(Идентификатор);
		
		Если НайденныеЭлементы.Количество() > 0 Тогда 
			Возврат НайденныеЭлементы[0];
		КонецЕсли;
	КонецЕсли;
	
	Если Иерархия <> Неопределено Тогда
		Иерархия.Добавить(Настройки);
	КонецЕсли;
	
	ТипНастройки = ТипЗнч(Настройки);
	
	Если ТипНастройки <> Тип("НастройкиКомпоновкиДанных") Тогда
		
		Если Настройки.ИдентификаторПользовательскойНастройки = Идентификатор Тогда
			
			Возврат Настройки;
			
		ИначеЕсли ТипНастройки = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
			
			Возврат ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки.Настройки, Идентификатор, Иерархия);
			
		ИначеЕсли ТипНастройки = Тип("КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных")
			ИЛИ ТипНастройки = Тип("КоллекцияЭлементовСтруктурыДиаграммыКомпоновкиДанных")
			ИЛИ ТипНастройки = Тип("КоллекцияЭлементовСтруктурыНастроекКомпоновкиДанных") Тогда
			
			Для Каждого ВложенныйЭлемент Из Настройки Цикл
				РезультатПоиска = ПолучитьОбъектПоПользовательскомуИдентификатору(ВложенныйЭлемент, Идентификатор, Иерархия);
				Если РезультатПоиска <> Неопределено Тогда
					Возврат РезультатПоиска;
				КонецЕсли;
			КонецЦикла;
			
			Если Иерархия <> Неопределено Тогда
				Иерархия.Удалить(Иерархия.ВГраница());
			КонецЕсли;
			
			Возврат Неопределено;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если Настройки.Выбор.ИдентификаторПользовательскойНастройки = Идентификатор Тогда
		Возврат Настройки.Выбор;
	ИначеЕсли Настройки.УсловноеОформление.ИдентификаторПользовательскойНастройки = Идентификатор Тогда
		Возврат Настройки.УсловноеОформление;
	КонецЕсли;
	
	Если ТипНастройки <> Тип("ТаблицаКомпоновкиДанных") И ТипНастройки <> Тип("ДиаграммаКомпоновкиДанных") Тогда
		Если Настройки.Отбор.ИдентификаторПользовательскойНастройки = Идентификатор Тогда
			Возврат Настройки.Отбор;
		ИначеЕсли Настройки.Порядок.ИдентификаторПользовательскойНастройки = Идентификатор Тогда
			Возврат Настройки.Порядок;
		КонецЕсли;
	КонецЕсли;
	
	Если ТипНастройки = Тип("НастройкиКомпоновкиДанных") Тогда
		РезультатПоиска = НайтиЭлементНастройки(Настройки.ПараметрыДанных, Идентификатор);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
	КонецЕсли;
	
	Если ТипНастройки <> Тип("ТаблицаКомпоновкиДанных") И ТипНастройки <> Тип("ДиаграммаКомпоновкиДанных") Тогда
		РезультатПоиска = НайтиЭлементНастройки(Настройки.Отбор, Идентификатор);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
	КонецЕсли;
	
	РезультатПоиска = НайтиЭлементНастройки(Настройки.УсловноеОформление, Идентификатор);
	Если РезультатПоиска <> Неопределено Тогда
		Возврат РезультатПоиска;
	КонецЕсли;
	
	Если ТипНастройки = Тип("ТаблицаКомпоновкиДанных") Тогда
		
		РезультатПоиска = ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки.Строки, Идентификатор, Иерархия);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
		
		РезультатПоиска = ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки.Колонки, Идентификатор, Иерархия);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
		
	ИначеЕсли ТипНастройки = Тип("ДиаграммаКомпоновкиДанных") Тогда
		
		РезультатПоиска = ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки.Точки, Идентификатор, Иерархия);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
		
		РезультатПоиска = ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки.Серии, Идентификатор, Иерархия);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
		
	Иначе
		
		РезультатПоиска = ПолучитьОбъектПоПользовательскомуИдентификатору(Настройки.Структура, Идентификатор, Иерархия);
		Если РезультатПоиска <> Неопределено Тогда
			Возврат РезультатПоиска;
		КонецЕсли;
		
	КонецЕсли;
	
	Если Иерархия <> Неопределено Тогда
		Иерархия.Удалить(Иерархия.ВГраница());
	КонецЕсли;
	
	Возврат Неопределено;
КонецФункции

// Находит доступную настройку для отбора или параметра.
//
// Параметры:
//   Настройки - НастройкиКомпоновкиДанных - коллекции настроек.
//   ЭлементНастройки - ЭлементОтбораКомпоновкиДанных
//                    - ЗначениеПараметраНастроекКомпоновкиДанных
//                    - НастройкиВложенногоОбъектаКомпоновкиДанных - значение элемента настройки.
//
// Возвращаемое значение:
//   ДоступноеПолеКомпоновкиДанных, ДоступныйПараметрКомпоновкиДанных,
//       ДоступныйОбъектНастройкиКомпоновкиДанных - Найденная доступная настройка.
//   Неопределено - если доступная настройка не существует.
//
Функция НайтиДоступнуюНастройку(Настройки, ЭлементНастройки) Экспорт
	Тип = ТипЗнч(ЭлементНастройки);
	Если Тип = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
		
		ЭлементОтбора = ЭлементНастройки;
		
		Если ЗначениеЗаполнено(ЭлементНастройки.ИдентификаторПользовательскойНастройки) Тогда 
			ЭлементОтбора = ПолучитьОбъектПоПользовательскомуИдентификатору(
				Настройки, ЭлементНастройки.ИдентификаторПользовательскойНастройки);
		КонецЕсли;
		
		Возврат НайтиДоступноеПолеКД(Настройки, ЭлементОтбора.ЛевоеЗначение);
		
	ИначеЕсли Тип = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
		
		Возврат НайтиДоступныйПараметрКД(Настройки, ЭлементНастройки.Параметр);
		
	ИначеЕсли Тип = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
		
		Возврат Настройки.ДоступныеОбъекты.Элементы.Найти(ЭлементНастройки.ИдентификаторОбъекта);
		
	КонецЕсли;
	
	Возврат Неопределено;
КонецФункции

// Находит параметры и отборы по значению.
//
// Параметры:
//   Настройки - ПользовательскиеНастройкиКомпоновкиДанных
//             - Массив - настройки,
//               элементы которых необходимо отобрать по определенным критериям.
//   Отбор               - Структура:
//       * Использование - Булево - использование настройки.
//       * Значение      - Неопределено - значение настройки.
//   ЭлементыНастроек    - Неопределено
//                       - КоллекцияЭлементовПользовательскихНастроекКомпоновкиДанных
//                       - КоллекцияЭлементовОтбораКомпоновкиДанных - элементы настроек,
//                         сравниваемые с критериями и помещаемые в результат,
//                         в случае соответствия критериям.
//   Результат           - Массив
//                       - Неопределено - см. возвращаемое значение.
//
// Возвращаемое значение:
//   Массив - найденные пользовательские настройки.
//
Функция ЭлементыНастроекОтобранные(Настройки, Отбор, ЭлементыНастроек = Неопределено, Результат = Неопределено) Экспорт
	ЭтоПользовательскиеНастройки = (ТипЗнч(Настройки) = Тип("ПользовательскиеНастройкиКомпоновкиДанных"));
	
	Если ЭлементыНастроек = Неопределено Тогда 
		ЭлементыНастроек = ?(ЭтоПользовательскиеНастройки, Настройки.Элементы, Настройки);
	КонецЕсли;
	
	Если Результат = Неопределено Тогда
		Результат = Новый Массив;
	КонецЕсли;
	
	Для Каждого Элемент Из ЭлементыНастроек Цикл
		ЭлементАнализируемый = Неопределено;
		
		Если ЭтоПользовательскиеНастройки Тогда 
			ЭлементАнализируемый = Настройки.Элементы.Найти(Элемент.ИдентификаторПользовательскойНастройки);
		КонецЕсли;
		
		Если ЭлементАнализируемый = Неопределено Тогда 
			ЭлементАнализируемый = Элемент;
		КонецЕсли;
		
		Если ТипЗнч(ЭлементАнализируемый) = Тип("ЭлементОтбораКомпоновкиДанных") 
			И ЭлементАнализируемый.Использование = Отбор.Использование
			И ЭлементАнализируемый.ПравоеЗначение = Отбор.Значение Тогда
			
			Результат.Добавить(ЭлементАнализируемый);
			
		ИначеЕсли ТипЗнч(ЭлементАнализируемый) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") 
			И ЭлементАнализируемый.Использование = Отбор.Использование
			И ЭлементАнализируемый.Значение = Отбор.Значение Тогда
			
			Результат.Добавить(ЭлементАнализируемый);
			
		ИначеЕсли ТипЗнч(ЭлементАнализируемый) = Тип("ОтборКомпоновкиДанных")
			Или ТипЗнч(ЭлементАнализируемый) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
			
			Если ЗначениеЗаполнено(ЭлементАнализируемый.ИдентификаторПользовательскойНастройки) Тогда 
				
				НайденныеЭлементы = Настройки.ПолучитьОсновныеНастройкиПоИдентификаторуПользовательскойНастройки(
					ЭлементАнализируемый.ИдентификаторПользовательскойНастройки); // ОтборКомпоновкиДанных, ГруппаЭлементовОтбораКомпоновкиДанных
				
				Если НайденныеЭлементы.Количество() > 0 Тогда
					ТекущиеЭлементыНастроек = НайденныеЭлементы.Получить(0); // ОтборКомпоновкиДанных, ГруппаЭлементовОтбораКомпоновкиДанных
					ЭлементыНастроекОтобранные(Настройки, Отбор, ТекущиеЭлементыНастроек.Элементы, Результат);
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Результат;
КонецФункции

Функция ИндексЭлементаНастройкиПоПути(Знач Путь, СвойствоЭлемента = Неопределено) Экспорт 
	ДоступныеСвойства = СтрРазделить("Использование, Значение, Список", ", ", Ложь);
	Для Каждого СвойствоЭлемента Из ДоступныеСвойства Цикл 
		Если СтрЗаканчиваетсяНа(Путь, СвойствоЭлемента) Тогда 
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	ОписаниеИндекса = Новый ОписаниеТипов("Число");
	
	ИндексЭлемента = СтрЗаменить(Путь, "КомпоновщикНастроекПользовательскиеНастройкиЭлемент", "");
	ИндексЭлемента = СтрЗаменить(ИндексЭлемента, СвойствоЭлемента, "");
	
	Возврат ОписаниеИндекса.ПривестиЗначение(ИндексЭлемента);
КонецФункции

#Область УстаревшиеПроцедурыИФункции

// Устарела. Следует использовать ОбщегоНазначенияКлиентСервер.ДополнитьСписок.
Функция ДополнитьСписок(СписокПриемник, СписокИсточник, КонтролироватьТип = Неопределено, ДобавлятьНовые = Истина) Экспорт
	
	Если СписокПриемник = Неопределено Или СписокИсточник = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат ОбщегоНазначенияКлиентСервер.ДополнитьСписок(СписокПриемник, СписокИсточник, КонтролироватьТип, ДобавлятьНовые);
	
КонецФункции

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Находит параметры в настройках компоновки по его имени.
// Если параметр не существует в пользовательских настройках, то его поиск выполняется в настройках варианта.
//
// Параметры:
//   НастройкиКД - НастройкиКомпоновкиДанных
//               - Неопределено -
//       Настройки варианта отчета, в которых будет осуществляться вторая итерация поиска значения.
//   ПользовательскиеНастройкиКД - ПользовательскиеНастройкиКомпоновкиДанных
//                               - Неопределено -
//       Пользовательские настройки, в которых будет осуществляться первая итерация поиска значения.
//   ИменаПараметров - Строка - имена параметров, перечисленные через запятую.
//       Имя каждого параметра должно удовлетворять требованиям образования имен переменных.
//
// Возвращаемое значение:
//   Структура - найденные значения параметров:
//       Ключ - имя параметра;
//       Значение - найденный параметр. Неопределено, если параметр не существует.
//
Функция НайтиПараметры(НастройкиКД, ПользовательскиеНастройкиКД, ИменаПараметров)
	Результат = Новый Структура;
	ИскомыеПараметры = Новый Соответствие;
	МассивИмен = СтрРазделить(ИменаПараметров, ",", Ложь);
	Количество = 0;
	Для Каждого ИмяПараметра Из МассивИмен Цикл
		ИскомыеПараметры.Вставить(СокрЛП(ИмяПараметра), Истина);
		Количество = Количество + 1;
	КонецЦикла;
	
	Если ПользовательскиеНастройкиКД <> Неопределено Тогда
		Для Каждого ЭлементКД Из ПользовательскиеНастройкиКД.Элементы Цикл
			Если ТипЗнч(ЭлементКД) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
				ИмяПараметра = Строка(ЭлементКД.Параметр);
				Если ИскомыеПараметры[ИмяПараметра] = Истина Тогда
					Результат.Вставить(ИмяПараметра, ЭлементКД);
					ИскомыеПараметры.Удалить(ИмяПараметра);
					Количество = Количество - 1;
					Если Количество = 0 Тогда
						Прервать;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если Количество > 0 Тогда
		Для Каждого КлючИЗначение Из ИскомыеПараметры Цикл
			Если НастройкиКД <> Неопределено Тогда
				ЭлементКД = НастройкиКД.ПараметрыДанных.Элементы.Найти(КлючИЗначение.Ключ);
			Иначе
				ЭлементКД = Неопределено;
			КонецЕсли;
			Результат.Вставить(КлючИЗначение.Ключ, ЭлементКД);
		КонецЦикла;
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

// Находит доступную настройку поля компоновки данных.
//
// Параметры:
//   НастройкиКД - НастройкиКомпоновкиДанных
//               - ГруппировкаКомпоновкиДанных - коллекции настроек.
//   Поле - Строка
//        - ПолеКомпоновкиДанных - имя поля.
//
// Возвращаемое значение:
//   ДоступноеПолеКомпоновкиДанных
//   Неопределено - когда доступная настройка поля не существует.
//
Функция НайтиДоступноеПолеКД(НастройкиКД, ПолеКД)
	Если ПолеКД = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если ТипЗнч(НастройкиКД) = Тип("ГруппировкаКомпоновкиДанных")
		Или ТипЗнч(НастройкиКД) = Тип("ГруппировкаТаблицыКомпоновкиДанных")
		Или ТипЗнч(НастройкиКД) = Тип("ГруппировкаДиаграммыКомпоновкиДанных") Тогда
		
		ДоступнаяНастройка = НастройкиКД.Отбор.ДоступныеПоляОтбора.НайтиПоле(ПолеКД);
	Иначе
		ДоступнаяНастройка = НастройкиКД.ДоступныеПоляОтбора.НайтиПоле(ПолеКД);
	КонецЕсли;
	
	Если ДоступнаяНастройка <> Неопределено Тогда
		Возврат ДоступнаяНастройка;
	КонецЕсли;
	
	МассивСтруктур = Новый Массив;
	МассивСтруктур.Добавить(НастройкиКД.Структура);
	Пока МассивСтруктур.Количество() > 0 Цикл
		
		СтруктураКД = МассивСтруктур[0];
		МассивСтруктур.Удалить(0);
		
		Для Каждого ЭлементСтруктурыКД Из СтруктураКД Цикл
			
			Если ТипЗнч(ЭлементСтруктурыКД) = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
				
				ДоступнаяНастройка = ЭлементСтруктурыКД.Настройки.ДоступныеПоляОтбора.НайтиПоле(ПолеКД);
				Если ДоступнаяНастройка <> Неопределено Тогда
					Возврат ДоступнаяНастройка;
				КонецЕсли;
				
				МассивСтруктур.Добавить(ЭлементСтруктурыКД.Настройки.Структура);
				
			ИначеЕсли ТипЗнч(ЭлементСтруктурыКД) = Тип("ГруппировкаКомпоновкиДанных") Тогда
				
				ДоступнаяНастройка = ЭлементСтруктурыКД.Отбор.ДоступныеПоляОтбора.НайтиПоле(ПолеКД);
				Если ДоступнаяНастройка <> Неопределено Тогда
					Возврат ДоступнаяНастройка;
				КонецЕсли;
				
				МассивСтруктур.Добавить(ЭлементСтруктурыКД.Структура);
				
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции

// Находит доступную настройку параметра компоновки данных.
//
// Параметры:
//   НастройкиКД - НастройкиКомпоновкиДанных - коллекции настроек.
//   ПараметрКД - ПараметрКомпоновкиДанных - имя параметра.
//
// Возвращаемое значение:
//   ДоступныйПараметрКомпоновкиДанных, Неопределено - доступная настройка для параметра.
//
Функция НайтиДоступныйПараметрКД(НастройкиКД, ПараметрКД)
	Если ПараметрКД = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если НастройкиКД.ПараметрыДанных.ДоступныеПараметры <> Неопределено Тогда
		// Настройки, которым принадлежат параметры данных, связаны с источником доступных настроек.
		ДоступнаяНастройка = НастройкиКД.ПараметрыДанных.ДоступныеПараметры.НайтиПараметр(ПараметрКД);
		Если ДоступнаяНастройка <> Неопределено Тогда
			Возврат ДоступнаяНастройка;
		КонецЕсли;
	КонецЕсли;
	
	МассивСтруктур = Новый Массив;
	МассивСтруктур.Добавить(НастройкиКД.Структура);
	Пока МассивСтруктур.Количество() > 0 Цикл
		
		СтруктураКД = МассивСтруктур[0];
		МассивСтруктур.Удалить(0);
		
		Для Каждого ЭлементСтруктурыКД Из СтруктураКД Цикл
			
			Если ТипЗнч(ЭлементСтруктурыКД) = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
				
				Если ЭлементСтруктурыКД.Настройки.ПараметрыДанных.ДоступныеПараметры <> Неопределено Тогда
					// Настройки, которым принадлежат параметры данных, связаны с источником доступных настроек.
					ДоступнаяНастройка = ЭлементСтруктурыКД.Настройки.ПараметрыДанных.ДоступныеПараметры.НайтиПараметр(ПараметрКД);
					Если ДоступнаяНастройка <> Неопределено Тогда
						Возврат ДоступнаяНастройка;
					КонецЕсли;
				КонецЕсли;
				
				МассивСтруктур.Добавить(ЭлементСтруктурыКД.Настройки.Структура);
				
			ИначеЕсли ТипЗнч(ЭлементСтруктурыКД) = Тип("ГруппировкаКомпоновкиДанных") Тогда
				
				МассивСтруктур.Добавить(ЭлементСтруктурыКД.Структура);
				
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции

// Определяет значения типа ГруппыИЭлементы в зависимости от вида сравнения (приоритетно) или исходного значения.
//
// Параметры:
//  Условие - ВидСравненияКомпоновкиДанных
//          - Неопределено - текущее значение вида сравнения.
//  ИсходноеЗначение - ИспользованиеГруппИЭлементов
//                   - ГруппыИЭлементы - текущее значение свойства
//                     ВыборГруппИЭлементов.
//
// Возвращаемое значение:
//   ГруппыИЭлементы - значение перечисления ГруппыИЭлементы.
//
Функция ЗначениеТипаГруппыИЭлементы(ИсходноеЗначение, Условие = Неопределено) Экспорт
	Если Условие <> Неопределено Тогда 
		Если Условие = ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии
			Или Условие = ВидСравненияКомпоновкиДанных.НеВСпискеПоИерархии Тогда 
			Если ИсходноеЗначение = ГруппыИЭлементы.Группы
				Или ИсходноеЗначение = ИспользованиеГруппИЭлементов.Группы Тогда 
				Возврат ГруппыИЭлементы.Группы;
			Иначе
				Возврат ГруппыИЭлементы.ГруппыИЭлементы;
			КонецЕсли;
		ИначеЕсли Условие = ВидСравненияКомпоновкиДанных.ВИерархии
			Или Условие = ВидСравненияКомпоновкиДанных.НеВИерархии Тогда 
			Возврат ГруппыИЭлементы.Группы;
		КонецЕсли;
	КонецЕсли;
	
	Если ТипЗнч(ИсходноеЗначение) = Тип("ГруппыИЭлементы") Тогда 
		Возврат ИсходноеЗначение;
	ИначеЕсли ИсходноеЗначение = ИспользованиеГруппИЭлементов.Элементы Тогда
		Возврат ГруппыИЭлементы.Элементы;
	ИначеЕсли ИсходноеЗначение = ИспользованиеГруппИЭлементов.ГруппыИЭлементы Тогда
		Возврат ГруппыИЭлементы.ГруппыИЭлементы;
	ИначеЕсли ИсходноеЗначение = ИспользованиеГруппИЭлементов.Группы Тогда
		Возврат ГруппыИЭлементы.Группы;
	КонецЕсли;
	
	Возврат ГруппыИЭлементы.Авто;
КонецФункции

// Загружает новые настройки в компоновщик без сброса пользовательских настроек.
//
// Параметры:
//  КомпоновщикНастроек - КомпоновщикНастроекКомпоновкиДанных - куда надо загрузить настройки.
//  Настройки - НастройкиКомпоновкиДанных - загружаемые настройки варианта.
//  ПользовательскиеНастройки - ПользовательскиеНастройкиКомпоновкиДанных
//                            - Неопределено - загружаемые пользовательские настройки.
//                              Если не указан, то пользовательские настройки не загружаются.
//  ФиксированныеНастройки - НастройкиКомпоновкиДанных
//                         - Неопределено - загружаемые фиксированные настройки.
//                           Если не указан, то фиксированные настройки не загружаются.
//
Функция ЗагрузитьНастройки(КомпоновщикНастроек, Настройки, ПользовательскиеНастройки = Неопределено, ФиксированныеНастройки = Неопределено) Экспорт
	НастройкиЗагружены = (ТипЗнч(Настройки) = Тип("НастройкиКомпоновкиДанных")
		И Настройки <> КомпоновщикНастроек.Настройки);
	
	Если НастройкиЗагружены Тогда
		Если ТипЗнч(ПользовательскиеНастройки) <> Тип("ПользовательскиеНастройкиКомпоновкиДанных") Тогда
			ПользовательскиеНастройки = КомпоновщикНастроек.ПользовательскиеНастройки;
		КонецЕсли;
		
		Если ТипЗнч(ФиксированныеНастройки) <> Тип("НастройкиКомпоновкиДанных") Тогда 
			ФиксированныеНастройки = КомпоновщикНастроек.ФиксированныеНастройки;
		КонецЕсли;
		
		ДоступныеЗначения = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
			КомпоновщикНастроек.Настройки.ДополнительныеСвойства, "ДоступныеЗначения");
		
		Если ДоступныеЗначения <> Неопределено Тогда 
			Настройки.ДополнительныеСвойства.Вставить("ДоступныеЗначения", ДоступныеЗначения);
		КонецЕсли;
		
		КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
	КонецЕсли;
	
	Если ТипЗнч(ПользовательскиеНастройки) = Тип("ПользовательскиеНастройкиКомпоновкиДанных")
		И ПользовательскиеНастройки <> КомпоновщикНастроек.ПользовательскиеНастройки Тогда
		КомпоновщикНастроек.ЗагрузитьПользовательскиеНастройки(ПользовательскиеНастройки);
	КонецЕсли;
	
	Если ТипЗнч(ФиксированныеНастройки) = Тип("НастройкиКомпоновкиДанных")
		И ФиксированныеНастройки <> КомпоновщикНастроек.ФиксированныеНастройки Тогда
		КомпоновщикНастроек.ЗагрузитьФиксированныеНастройки(ФиксированныеНастройки);
	КонецЕсли;
	
	Возврат НастройкиЗагружены;
КонецФункции

Процедура ОповеститьОИзмененииНастроек(Форма) Экспорт 
	
	Если Не Форма.ПользовательскиеНастройкиМодифицированы Тогда 
		Возврат;
	КонецЕсли;
	
	ТекстСостояния = НСтр("ru = 'Изменились настройки. Нажмите ""Сформировать"" для получения отчета.'");
	ОтобразитьСостояниеОтчета(Форма, ТекстСостояния);
	
КонецПроцедуры

// Параметры:
//  Форма - ФормаКлиентскогоПриложения
//  ТекстСостояния - Строка
//  КартинкаСостояния - Неопределено
//
Процедура ОтобразитьСостояниеОтчета(Форма, Знач ТекстСостояния = "", Знач КартинкаСостояния = Неопределено) Экспорт 
	
	ПолеОтчета = Форма.Элементы.Найти("ОтчетТабличныйДокумент");
	Если ПолеОтчета = Неопределено Тогда 
		Возврат;
	КонецЕсли;
	
	ОтображатьСостояние = Не ПустаяСтрока(ТекстСостояния);
	
	Если КартинкаСостояния = Неопределено Или Не ОтображатьСостояние Тогда 
		КартинкаСостояния = Новый Картинка;
	КонецЕсли;
	
	ОтображениеСостояния = ПолеОтчета.ОтображениеСостояния;
	ОтображениеСостояния.Видимость = ОтображатьСостояние;
	ОтображениеСостояния.ДополнительныйРежимОтображения = 
		?(ОтображатьСостояние, ДополнительныйРежимОтображения.Неактуальность, ДополнительныйРежимОтображения.НеИспользовать);
	ОтображениеСостояния.Картинка = КартинкаСостояния;
	ОтображениеСостояния.Текст = ТекстСостояния;

	ПолеОтчета.ТолькоПросмотр = ОтображатьСостояние 
		Или ПолеОтчета.Вывод = ИспользованиеВывода.Запретить;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Локальные служебные процедуры и функции.

// Находит общую настройку компоновки данных по идентификатору.
Функция НайтиЭлементНастройки(ЭлементНастройки, ИдентификаторПользовательскойНастройки)
	// Поиск элемента с заданным значением свойства ИдентификаторПользовательскойНастройки (ИПН).
	
	Группы = Новый Массив;
	Группы.Добавить(ЭлементНастройки.Элементы);
	Индекс = 0;
	
	Пока Индекс < Группы.Количество() Цикл
		
		КоллекцияЭлементов = Группы[Индекс];
		Индекс = Индекс + 1;
		Для Каждого ПодчиненныйЭлемент Из КоллекцияЭлементов Цикл
			Если ТипЗнч(ПодчиненныйЭлемент) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда
				// Не содержит ИПН; Коллекция вложенных элементов не содержит ИПН.
			ИначеЕсли ТипЗнч(ПодчиненныйЭлемент) = Тип("ЗначениеПараметраКомпоновкиДанных") Тогда
				// Не содержит ИПН; Коллекция вложенных элементов может содержать ИПН.
				Группы.Добавить(ПодчиненныйЭлемент.ЗначенияВложенныхПараметров);
			ИначеЕсли ПодчиненныйЭлемент.ИдентификаторПользовательскойНастройки = ИдентификаторПользовательскойНастройки Тогда
				// Найден нужный элемент.
				Возврат ПодчиненныйЭлемент;
			Иначе
				// Содержит ИПН; Коллекция вложенных элементов может содержать ИПН.
				Если ТипЗнч(ПодчиненныйЭлемент) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
					Группы.Добавить(ПодчиненныйЭлемент.Элементы);
				ИначеЕсли ТипЗнч(ПодчиненныйЭлемент) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
					Группы.Добавить(ПодчиненныйЭлемент.ЗначенияВложенныхПараметров);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции

// Возвращает значение параметра данных по полю компоновки данных.
//
// Параметры:
//  Настройки - НастройкиКомпоновкиДанных - текущие настройки отчета.
//  ПользовательскиеНастройки - КоллекцияЭлементовПользовательскихНастроекКомпоновкиДанных  - текущие пользовательские
//                              настройки отчета.
//  Поле - ПолеКомпоновкиДанных - поле, являющееся критерием поиска.
//
// Возвращаемое значение:
//   ЗначениеПараметраКомпоновкиДанных, Неопределено - значение параметра данных по полю компоновки данных.
//
Функция ЗначениеПараметраВыбора(Настройки, ПользовательскиеНастройки, Поле, РежимИзмененияВарианта)
	Значение = ЗначениеПараметраДанныхПоПолю(Настройки, ПользовательскиеНастройки, Поле, РежимИзмененияВарианта);
	
	Если Значение = Неопределено Тогда 
		ЭлементыОтбора = Настройки.Отбор.Элементы;
		НайтиЗначенияПоляЭлементовОтбора(Поле, ЭлементыОтбора, ПользовательскиеНастройки, Значение, РежимИзмененияВарианта);
	КонецЕсли;
	
	Если ТипЗнч(Значение) = Тип("СтандартнаяДатаНачала") Тогда 
		Возврат Значение.Дата;
	КонецЕсли;
	
	Если ТипЗнч(Значение) = Тип("СтандартныйПериод") Тогда 
		Возврат Значение.ДатаОкончания;
	КонецЕсли;
	
	Возврат Значение;
КонецФункции

// Возвращает значение параметра компоновки данных, найденное по полю компоновки данных.
//
// Параметры:
//  Настройки - НастройкиКомпоновкиДанных - настройки в которых осуществляется поиск.
//  ПользовательскиеНастройки - КоллекцияЭлементовПользовательскихНастроекКомпоновкиДанных - коллекция текущих
//                              пользовательских настроек.
//
// Возвращаемое значение:
//   ЗначениеПараметраКомпоновкиДанных, Неопределено - значение параметра компоновки данных,
//                                                     найденное по полю компоновки данных.
//
Функция ЗначениеПараметраДанныхПоПолю(Настройки, ПользовательскиеНастройки, Поле, РежимИзмененияВарианта)
	Если ТипЗнч(Настройки) <> Тип("НастройкиКомпоновкиДанных") Тогда 
		Возврат Неопределено;
	КонецЕсли;
	
	ЭлементыНастроек = Настройки.ПараметрыДанных.Элементы;
	Для Каждого Элемент Из ЭлементыНастроек Цикл 
		ЭлементПользовательский = ПользовательскиеНастройки.Найти(Элемент.ИдентификаторПользовательскойНастройки);
		ЭлементАнализируемый = ?(РежимИзмененияВарианта Или ЭлементПользовательский = Неопределено, Элемент, ЭлементПользовательский);
		
		Поля = Новый Массив;
		Поля.Добавить(Новый ПолеКомпоновкиДанных(Строка(Элемент.Параметр)));
		Поля.Добавить(Новый ПолеКомпоновкиДанных("ПараметрыДанных." + Строка(Элемент.Параметр)));
		
		Если ЭлементАнализируемый.Использование
			И (Поля[0] = Поле Или Поля[1] = Поле)
			И ЗначениеЗаполнено(ЭлементАнализируемый.Значение)
			И ТипЗнч(ЭлементАнализируемый.Значение) <> Тип("СписокЗначений") Тогда 
			
			Возврат ЭлементАнализируемый.Значение;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции

Процедура НайтиЗначенияПоляЭлементовОтбора(Поле, ЭлементыОтбора, ПользовательскиеНастройки, Значение, РежимИзмененияВарианта)
	Если ЗначениеЗаполнено(Значение) Тогда 
		Возврат;
	КонецЕсли;
	
	Для Каждого Элемент Из ЭлементыОтбора Цикл 
		ЭлементПользовательский = ПользовательскиеНастройки.Найти(Элемент.ИдентификаторПользовательскойНастройки);
		ЭлементАнализируемый = ?(РежимИзмененияВарианта Или ЭлементПользовательский = Неопределено, Элемент, ЭлементПользовательский);
		
		Если ТипЗнч(ЭлементАнализируемый) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда 
			НайтиЗначенияПоляЭлементовОтбора(Поле, Элемент.Элементы, ПользовательскиеНастройки, Значение, РежимИзмененияВарианта);
		Иначе
			Если Элемент.ЛевоеЗначение = Поле
				И ЭлементАнализируемый.Использование
				И ЭлементАнализируемый.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно
				И ЗначениеЗаполнено(ЭлементАнализируемый.ПравоеЗначение) Тогда 
				
				Значение = ЭлементАнализируемый.ПравоеЗначение; 
				Прервать;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Унификация формы отчета и формы настроек отчета.

// Возвращает представление элемента условного оформления.
//
// Параметры:
//  ЭлементКД - ЭлементУсловногоОформленияКомпоновкиДанных  - элемент оформления, представление которого необходимо определить.
//  НастройкаВариантаКД - НастройкиКомпоновкиДанных - текущие настройки варианта отчета.
//
// Возвращаемое значение:
//   Строка - представление элемента условного оформления.
//
Функция ПредставлениеЭлементаУсловногоОформления(ЭлементКД, НастройкаВариантаКД, Состояние) Экспорт
	ПредставлениеОформления = ПредставлениеОформления(ЭлементКД.Оформление);
	Если ПредставлениеОформления = "" Тогда
		ПредставлениеОформления = НСтр("ru = 'Не оформлять'");
	КонецЕсли;
	ДоступныСведенияИзВарианта = (НастройкаВариантаКД <> Неопределено И НастройкаВариантаКД <> ЭлементКД);
	
	ПредставлениеПолей = ПредставлениеОформляемыхПолей(ЭлементКД.Поля, Состояние);
	Если ПредставлениеПолей = "" И ДоступныСведенияИзВарианта Тогда
		ПредставлениеПолей = ПредставлениеОформляемыхПолей(НастройкаВариантаКД.Поля, Состояние);
	КонецЕсли;
	Если ПредставлениеПолей = "" Тогда
		ПредставлениеПолей = НСтр("ru = 'Все поля'");
	Иначе
		ПредставлениеПолей = НСтр("ru = 'Поля:'") + " " + ПредставлениеПолей;
	КонецЕсли;
	
	ПредставлениеОтбора = ПредставлениеОтбора(ЭлементКД.Отбор, ЭлементКД.Отбор.Элементы, Состояние);
	Если ПредставлениеОтбора = "" И ДоступныСведенияИзВарианта Тогда
		ПредставлениеОтбора = ПредставлениеОтбора(НастройкаВариантаКД.Отбор, НастройкаВариантаКД.Отбор.Элементы, Состояние);
	КонецЕсли;
	Если ПредставлениеОтбора = "" Тогда
		Разделитель = "";
	Иначе
		Разделитель = "; ";
		ПредставлениеОтбора = НСтр("ru = 'Условие:'") + " " + ПредставлениеОтбора;
	КонецЕсли;
	
	Возврат ПредставлениеОформления + " (" + ПредставлениеПолей + Разделитель + ПредставлениеОтбора + ")";
КонецФункции

Функция ПредставлениеОформления(ОформлениеКД)
	Представление = "";
	Для Каждого ЭлементКД Из ОформлениеКД.Элементы Цикл
		Если ЭлементКД.Использование Тогда
			ДоступныйПараметрКД = ОформлениеКД.ДоступныеПараметры.НайтиПараметр(ЭлементКД.Параметр);
			Если ДоступныйПараметрКД <> Неопределено И ЗначениеЗаполнено(ДоступныйПараметрКД.Заголовок) Тогда
				ПредставлениеКлюча = ДоступныйПараметрКД.Заголовок;
			Иначе
				ПредставлениеКлюча = Строка(ЭлементКД.Параметр);
			КонецЕсли;
			
			Если ТипЗнч(ЭлементКД.Значение) = Тип("Цвет") Тогда
				ПредставлениеЗначения = ПредставлениеЦвета(ЭлементКД.Значение);
			Иначе
				ПредставлениеЗначения = Строка(ЭлементКД.Значение);
			КонецЕсли;
			
			Представление = Представление
				+ ?(Представление = "", "", ", ")
				+ ПредставлениеКлюча
				+ ?(ПредставлениеЗначения = "", "", ": " + ПредставлениеЗначения);
		КонецЕсли;
	КонецЦикла;
	Возврат Представление;
КонецФункции

// Параметры:
//  Цвет - Цвет
// Возвращаемое значение:
//  Строка
//
Функция ПредставлениеЦвета(Цвет)
	Если Цвет.Вид = ВидЦвета.ЭлементСтиля Тогда
		Представление = Строка(Цвет);
		Представление = Сред(Представление, СтрНайти(Представление, ":")+1);
		Представление = ИмяВПредставление(Представление);
	ИначеЕсли Цвет.Вид = ВидЦвета.WebЦвет
		Или Цвет.Вид = ВидЦвета.WindowsЦвет Тогда
		Представление = СтрЛевДоСимвола(Строка(Цвет), " (");
	ИначеЕсли Цвет.Вид = ВидЦвета.Абсолютный Тогда
		Представление = Строка(Цвет);
		Если Представление = "0, 0, 0" Тогда
			Представление = НСтр("ru = 'Черный'");
		ИначеЕсли Представление = "255, 255, 255" Тогда
			Представление = НСтр("ru = 'Белый'");
		КонецЕсли;
	ИначеЕсли Цвет.Вид = ВидЦвета.АвтоЦвет Тогда
		Представление = НСтр("ru = 'Авто'");
	Иначе
		Представление = "";
	КонецЕсли;
	Возврат Представление;
КонецФункции

Функция ИмяВПредставление(Знач ИсходнаяСтрока)
	Результат = "";
	ЭтоПервыйСимвол = Истина;
	Для НомерСимвола = 1 По СтрДлина(ИсходнаяСтрока) Цикл
		КодСимвола = КодСимвола(ИсходнаяСтрока, НомерСимвола);
		Символ = Символ(КодСимвола);
		Если ЭтоПервыйСимвол Тогда
			Если Не ПустаяСтрока(Символ) Тогда
				Результат = Результат + Символ;
				ЭтоПервыйСимвол = Ложь;
			КонецЕсли;
		Иначе
			Если (КодСимвола >= 65 И КодСимвола <= 90)
				Или (КодСимвола >= 1040 И КодСимвола <= 1071) Тогда
				Символ = " " + НРег(Символ);
			ИначеЕсли Символ = "_" Тогда
				Символ = " ";
			КонецЕсли;
			Результат = Результат + Символ;
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции

Функция ПредставлениеОформляемыхПолей(ОформляемыеПоляКД, Состояние)
	Представление = "";
	
	Для Каждого ОформляемоеПолеКД Из ОформляемыеПоляКД.Элементы Цикл
		Если Не ОформляемоеПолеКД.Использование Тогда
			Продолжить;
		КонецЕсли;
		
		ДоступноеПолеКД = ОформляемыеПоляКД.ДоступныеПоляОформляемыхПолей.НайтиПоле(ОформляемоеПолеКД.Поле);
		Если ДоступноеПолеКД = Неопределено Тогда
			Состояние = "ПометкаУдаления";
			ПредставлениеПоля = Строка(ОформляемоеПолеКД.Поле);
		Иначе
			Если ЗначениеЗаполнено(ДоступноеПолеКД.Заголовок) Тогда
				ПредставлениеПоля = ДоступноеПолеКД.Заголовок;
			Иначе
				ПредставлениеПоля = Строка(ОформляемоеПолеКД.Поле);
			КонецЕсли;
		КонецЕсли;
		Представление = Представление + ?(Представление = "", "", ", ") + ПредставлениеПоля;
		
	КонецЦикла;
	
	Возврат Представление;
КонецФункции

Функция ПредставлениеОтбора(УзелКД, НаборСтрокКД, Состояние)
	Представление = "";
	
	Для Каждого ЭлементКД Из НаборСтрокКД Цикл
		Если Не ЭлементКД.Использование Тогда
			Продолжить;
		КонецЕсли;
		
		Если ТипЗнч(ЭлементКД) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
			
			ПредставлениеГруппы = Строка(ЭлементКД.ТипГруппы);
			ПредставлениеВложенных = ПредставлениеОтбора(УзелКД, ЭлементКД.Элементы, Состояние);
			Если ПредставлениеВложенных = "" Тогда
				Продолжить;
			КонецЕсли;
			ПредставлениеЭлемента = ПредставлениеГруппы + "(" + ПредставлениеВложенных + ")";
			
		ИначеЕсли ТипЗнч(ЭлементКД) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
			
			ДоступноеПолеОтбораКД = УзелКД.ДоступныеПоляОтбора.НайтиПоле(ЭлементКД.ЛевоеЗначение);
			Если ДоступноеПолеОтбораКД = Неопределено Тогда
				Состояние = "ПометкаУдаления";
				ПредставлениеПоля = Строка(ЭлементКД.ЛевоеЗначение);
			Иначе
				Если ЗначениеЗаполнено(ДоступноеПолеОтбораКД.Заголовок) Тогда
					ПредставлениеПоля = ДоступноеПолеОтбораКД.Заголовок;
				Иначе
					ПредставлениеПоля = Строка(ЭлементКД.ЛевоеЗначение);
				КонецЕсли;
			КонецЕсли;
			
			ПредставлениеЗначения = Строка(ЭлементКД.ПравоеЗначение);
			
			Если ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно Тогда
				ПредставлениеУсловия = "=";
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеРавно Тогда
				ПредставлениеУсловия = "<>";
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше Тогда
				ПредставлениеУсловия = ">";
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно Тогда
				ПредставлениеУсловия = ">=";
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше Тогда
				ПредставлениеУсловия = "<";
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.МеньшеИлиРавно Тогда
				ПредставлениеУсловия = "<=";
			
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИерархии Тогда
				ПредставлениеУсловия = НСтр("ru = 'В группе'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВИерархии Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не в группе'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке Тогда
				ПредставлениеУсловия = НСтр("ru = 'В списке'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСписке Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не в списке'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии Тогда
				ПредставлениеУсловия = НСтр("ru = 'В списке включая подчиненные'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСпискеПоИерархии Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не в списке включая подчиненные'");
			
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит Тогда
				ПредставлениеУсловия = НСтр("ru = 'Содержит'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеСодержит Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не содержит'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.Подобно Тогда
				ПредставлениеУсловия = НСтр("ru = 'Соответствует шаблону'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеПодобно Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не соответствует шаблону'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НачинаетсяС Тогда
				ПредставлениеУсловия = НСтр("ru = 'Начинается с'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеНачинаетсяС Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не начинается с'");
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено Тогда
				ПредставлениеУсловия = НСтр("ru = 'Заполнено'");
				ПредставлениеЗначения = "";
			ИначеЕсли ЭлементКД.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено Тогда
				ПредставлениеУсловия = НСтр("ru = 'Не заполнено'");
				ПредставлениеЗначения = "";
			КонецЕсли;
			
			ПредставлениеЭлемента = СокрЛП(ПредставлениеПоля + " " + ПредставлениеУсловия + " " + ПредставлениеЗначения);
			
		Иначе
			Продолжить;
		КонецЕсли;
		
		Представление = Представление + ?(Представление = "", "", ", ") + ПредставлениеЭлемента;
		
	КонецЦикла;
	
	Возврат Представление;
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Прочее

Функция ТипНастройкиСтрокой(Тип) Экспорт
	Если Тип = Тип("НастройкиКомпоновкиДанных") Тогда
		Возврат "Настройки";
	ИначеЕсли Тип = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
		Возврат "НастройкиВложенногоОбъекта";
	
	ИначеЕсли Тип = Тип("ОтборКомпоновкиДанных") Тогда
		Возврат "Отбор";
	ИначеЕсли Тип = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
		Возврат "ЭлементОтбора";
	ИначеЕсли Тип = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
		Возврат "ГруппаЭлементовОтбора";
	
	ИначеЕсли Тип = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
		Возврат "ЗначениеПараметраНастроек";
	
	ИначеЕсли Тип = Тип("ГруппировкаКомпоновкиДанных") Тогда
		Возврат "Группировка";
	ИначеЕсли Тип = Тип("ПоляГруппировкиКомпоновкиДанных") Тогда
		Возврат "ПоляГруппировки";
	ИначеЕсли Тип = Тип("КоллекцияПолейГруппировкиКомпоновкиДанных") Тогда
		Возврат "КоллекцияПолейГруппировки";
	ИначеЕсли Тип = Тип("ПолеГруппировкиКомпоновкиДанных") Тогда
		Возврат "ПолеГруппировки";
	ИначеЕсли Тип = Тип("АвтоПолеГруппировкиКомпоновкиДанных") Тогда
		Возврат "АвтоПолеГруппировки";
	
	ИначеЕсли Тип = Тип("ВыбранныеПоляКомпоновкиДанных") Тогда
		Возврат "ВыбранныеПоля";
	ИначеЕсли Тип = Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
		Возврат "ВыбранноеПоле";
	ИначеЕсли Тип = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда
		Возврат "ГруппаВыбранныхПолей";
	ИначеЕсли Тип = Тип("АвтоВыбранноеПолеКомпоновкиДанных") Тогда
		Возврат "АвтоВыбранноеПоле";
	
	ИначеЕсли Тип = Тип("ПорядокКомпоновкиДанных") Тогда
		Возврат "Порядок";
	ИначеЕсли Тип = Тип("ЭлементПорядкаКомпоновкиДанных") Тогда
		Возврат "ЭлементПорядка";
	ИначеЕсли Тип = Тип("АвтоЭлементПорядкаКомпоновкиДанных") Тогда
		Возврат "АвтоЭлементПорядка";
	
	ИначеЕсли Тип = Тип("УсловноеОформлениеКомпоновкиДанных") Тогда
		Возврат "УсловноеОформление";
	ИначеЕсли Тип = Тип("ЭлементУсловногоОформленияКомпоновкиДанных") Тогда
		Возврат "ЭлементУсловногоОформления";
	
	ИначеЕсли Тип = Тип("СтруктураНастроекКомпоновкиДанных") Тогда
		Возврат "СтруктураНастроек";
	ИначеЕсли Тип = Тип("КоллекцияЭлементовСтруктурыНастроекКомпоновкиДанных") Тогда
		Возврат "КоллекцияЭлементовСтруктурыНастроек";
	
	ИначеЕсли Тип = Тип("ТаблицаКомпоновкиДанных") Тогда
		Возврат "Таблица";
	ИначеЕсли Тип = Тип("ГруппировкаТаблицыКомпоновкиДанных") Тогда
		Возврат "ГруппировкаТаблицы";
	ИначеЕсли Тип = Тип("КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных") Тогда
		Возврат "КоллекцияЭлементовСтруктурыТаблицы";
	
	ИначеЕсли Тип = Тип("ДиаграммаКомпоновкиДанных") Тогда
		Возврат "Диаграмма";
	ИначеЕсли Тип = Тип("ГруппировкаДиаграммыКомпоновкиДанных") Тогда
		Возврат "ГруппировкаДиаграммы";
	ИначеЕсли Тип = Тип("КоллекцияЭлементовСтруктурыДиаграммыКомпоновкиДанных") Тогда
		Возврат "КоллекцияЭлементовСтруктурыДиаграммы";
	
	ИначеЕсли Тип = Тип("ЗначенияПараметровДанныхКомпоновкиДанных") Тогда
		Возврат "ЗначенияПараметровДанных";
	
	Иначе
		Возврат "";
	КонецЕсли;
КонецФункции

Функция СкопироватьРекурсивно(Знач Узел, Знач ЧтоКопировать, Знач КудаВставить, Знач Индекс, Соответствие = Неопределено, БезСтруктуры = Ложь) Экспорт
	Если Соответствие = Неопределено Тогда
		Соответствие = Новый Соответствие;
	КонецЕсли;
	
	ТипЭлемента = ТипЗнч(ЧтоКопировать);
	ПараметрыКопирования = ПараметрыКопирования(ТипЭлемента, КудаВставить, БезСтруктуры);
	
	Если ПараметрыКопирования.НужноУказыватьТипЭлемента Тогда
		Если Индекс = Неопределено Тогда
			НоваяСтрока = КудаВставить.Добавить(ТипЭлемента);
		Иначе
			НоваяСтрока = КудаВставить.Вставить(Индекс, ТипЭлемента);
		КонецЕсли;
	Иначе
		Если Индекс = Неопределено Тогда
			НоваяСтрока = КудаВставить.Добавить();
		Иначе
			НоваяСтрока = КудаВставить.Вставить(Индекс);
		КонецЕсли;
	КонецЕсли;
	
	ЗаполнитьСвойстваРекурсивно(Узел, НоваяСтрока, ЧтоКопировать, Соответствие, ПараметрыКопирования);
	
	Возврат НоваяСтрока;
КонецФункции

Функция ПараметрыКопирования(ТипЭлемента, Коллекция, БезСтруктуры = Ложь)
	Результат = Новый Структура;
	Результат.Вставить("НужноУказыватьТипЭлемента", Ложь);
	Результат.Вставить("ИсключаяСвойства", Неопределено);
	Результат.Вставить("ЕстьНастройки", Ложь);
	Результат.Вставить("ЕстьЭлементы", Ложь);
	Результат.Вставить("ЕстьВыбор", Ложь);
	Результат.Вставить("ЕстьОтбор", Ложь);
	Результат.Вставить("ЕстьПараметрыВывода", Ложь);
	Результат.Вставить("ЕстьПараметрыДанных", Ложь);
	Результат.Вставить("ЕстьПользовательскиеПоля", Ложь);
	Результат.Вставить("ЕстьПоляГруппировки", Ложь);
	Результат.Вставить("ЕстьПорядок", Ложь);
	Результат.Вставить("ЕстьСтруктура", Ложь);
	Результат.Вставить("ЕстьУсловноеОформление", Ложь);
	Результат.Вставить("ЕстьКолонкиИСтроки", Ложь);
	Результат.Вставить("ЕстьСерииИТочки", Ложь);
	Результат.Вставить("ЕстьЗначенияВложенныхПараметров", Ложь);
	Результат.Вставить("ЕстьПоляИОформление", Ложь);
	
	Если ТипЭлемента = Тип("ГруппаВыбранныхПолейКомпоновкиДанных")
		Или ТипЭлемента = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
		
		Результат.НужноУказыватьТипЭлемента = Истина;
		Результат.ИсключаяСвойства = "Родитель";
		Результат.ЕстьЭлементы = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("ВыбранноеПолеКомпоновкиДанных")
		Или ТипЭлемента = Тип("АвтоВыбранноеПолеКомпоновкиДанных")
		Или ТипЭлемента = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
		
		Результат.ИсключаяСвойства = "Родитель";
		Результат.НужноУказыватьТипЭлемента = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("ЗначениеПараметраКомпоновкиДанных")
		Или ТипЭлемента = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
		
		Результат.ИсключаяСвойства = "Родитель";
		
	ИначеЕсли ТипЭлемента = Тип("ПолеГруппировкиКомпоновкиДанных")
		Или ТипЭлемента = Тип("АвтоПолеГруппировкиКомпоновкиДанных")
		Или ТипЭлемента = Тип("ЭлементПорядкаКомпоновкиДанных")
		Или ТипЭлемента = Тип("АвтоЭлементПорядкаКомпоновкиДанных") Тогда
		
		Результат.НужноУказыватьТипЭлемента = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("ЭлементУсловногоОформленияКомпоновкиДанных") Тогда
		
		Результат.ЕстьОтбор = Истина;
		Результат.ЕстьПоляИОформление = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("ГруппировкаКомпоновкиДанных")
		Или ТипЭлемента = Тип("ГруппировкаТаблицыКомпоновкиДанных")
		Или ТипЭлемента = Тип("ГруппировкаДиаграммыКомпоновкиДанных")Тогда
		
		Результат.ИсключаяСвойства = "Родитель";
		ТипКоллекции = ТипЗнч(Коллекция);
		Если ТипКоллекции = Тип("КоллекцияЭлементовСтруктурыНастроекКомпоновкиДанных") Тогда
			Результат.НужноУказыватьТипЭлемента = Истина;
			ТипЭлемента = Тип("ГруппировкаКомпоновкиДанных"); // Подмена типа на поддерживаемый.
		КонецЕсли;
		
		Результат.ЕстьВыбор = Истина;
		Результат.ЕстьОтбор = Истина;
		Результат.ЕстьПараметрыВывода = Истина;
		Результат.ЕстьПоляГруппировки = Истина;
		Результат.ЕстьПорядок = Истина;
		Результат.ЕстьСтруктура = Не БезСтруктуры;
		Результат.ЕстьУсловноеОформление = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("ТаблицаКомпоновкиДанных") Тогда
		
		Результат.ИсключаяСвойства = "Родитель";
		Результат.НужноУказыватьТипЭлемента = Истина;
		
		Результат.ЕстьВыбор = Истина;
		Результат.ЕстьКолонкиИСтроки = Истина;
		Результат.ЕстьПараметрыВывода = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("ДиаграммаКомпоновкиДанных") Тогда
		
		Результат.ИсключаяСвойства = "Родитель";
		Результат.НужноУказыватьТипЭлемента = Истина;
		
		Результат.ЕстьВыбор = Истина;
		Результат.ЕстьСерииИТочки = Истина;
		Результат.ЕстьПараметрыВывода = Истина;
		
	ИначеЕсли ТипЭлемента = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
		
		Результат.ИсключаяСвойства = "Родитель";
		Результат.НужноУказыватьТипЭлемента = Истина;
		Результат.ЕстьНастройки = Истина;
		
		Результат.ЕстьВыбор = Истина;
		Результат.ЕстьОтбор = Истина;
		Результат.ЕстьПараметрыВывода = Истина;
		Результат.ЕстьПараметрыДанных = Истина;
		Результат.ЕстьПользовательскиеПоля = Истина;
		Результат.ЕстьПорядок = Истина;
		Результат.ЕстьСтруктура = Не БезСтруктуры;
		Результат.ЕстьУсловноеОформление = Истина;
		
	ИначеЕсли ТипЭлемента <> Тип("ДанныеФормыЭлементДерева") Тогда 
		
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Копирование элементов ""%1"" не поддерживается'"), ТипЭлемента);
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Возвращает элемент настройки, который заполняется на основании однотипного элемента.
//
// Параметры:
//  Узел - НастройкиКомпоновкиДанных - настройки отчета.
//  ЧтоЗаполнить - НастройкиКомпоновкиДанных
//               - ВыбранныеПоляКомпоновкиДанных
//               - ОтборКомпоновкиДанных
//               - ГруппировкаКомпоновкиДанных
//               - ТаблицаКомпоновкиДанных
//               - ДиаграммаКомпоновкиДанных
//               - ЭлементУсловногоОформленияКомпоновкиДанных - элемент настройки, который заполняется.
//  ЧемЗаполнить - НастройкиКомпоновкиДанных
//               - ВыбранныеПоляКомпоновкиДанных
//               - ОтборКомпоновкиДанных
//               - ГруппировкаКомпоновкиДанных
//               - ТаблицаКомпоновкиДанных
//               - ДиаграммаКомпоновкиДанных
//               - ЭлементУсловногоОформленияКомпоновкиДанных - элемент настройки-основание.
//
// Возвращаемое значение:
//   НастройкиКомпоновкиДанных,
//   ВыбранныеПоляКомпоновкиДанных,
//   ОтборКомпоновкиДанных,
//   ГруппировкаКомпоновкиДанных,
//   ТаблицаКомпоновкиДанных,
//   ДиаграммаКомпоновкиДанных,
//   ЭлементУсловногоОформленияКомпоновкиДанных - элемент настройки, который заполняется.
//
Функция ЗаполнитьСвойстваРекурсивно(Узел, ЧтоЗаполнить, ЧемЗаполнить, Соответствие = Неопределено, ПараметрыКопирования = Неопределено, БезСтруктуры = Ложь) Экспорт
	Если Соответствие = Неопределено Тогда
		Соответствие = Новый Соответствие;
	КонецЕсли;
	
	Если ПараметрыКопирования = Неопределено Тогда
		ПараметрыКопирования = ПараметрыКопирования(ТипЗнч(ЧемЗаполнить), Неопределено, БезСтруктуры);
	КонецЕсли;
	
	Если ПараметрыКопирования.ИсключаяСвойства <> "*" Тогда
		ЗаполнитьЗначенияСвойств(ЧтоЗаполнить, ЧемЗаполнить, , ПараметрыКопирования.ИсключаяСвойства);
	КонецЕсли;
	
	ЭтоДанныеФормыЭлементДерева = ТипЗнч(ЧемЗаполнить) = Тип("ДанныеФормыЭлементДерева");
	Если ЭтоДанныеФормыЭлементДерева Тогда
		Соответствие.Вставить(ЧемЗаполнить, ЧтоЗаполнить);
		
		КоллекцияВложенных = ?(ЭтоДанныеФормыЭлементДерева, ЧемЗаполнить.ПолучитьЭлементы(), ЧемЗаполнить.Строки);
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ?(ЭтоДанныеФормыЭлементДерева, ЧтоЗаполнить.ПолучитьЭлементы(), ЧтоЗаполнить.Строки);
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
		
		Возврат ЧтоЗаполнить;
	КонецЕсли;
		
	СтарыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(ЧемЗаполнить);
	НовыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(ЧтоЗаполнить);
	Соответствие.Вставить(СтарыйИдентификатор, НовыйИдентификатор);
	
	Если ПараметрыКопирования.ЕстьНастройки Тогда
		ЧтоЗаполнить.УстановитьИдентификатор(ЧемЗаполнить.ИдентификаторОбъекта);
		ЧтоЗаполнить = ЧтоЗаполнить.Настройки; // НастройкиКомпоновкиДанных, ВыбранныеПоляКомпоновкиДанных, ОтборКомпоновкиДанных, ГруппировкаКомпоновкиДанных, ТаблицаКомпоновкиДанных, ДиаграммаКомпоновкиДанных, ЭлементУсловногоОформленияКомпоновкиДанных
		ЧемЗаполнить = ЧемЗаполнить.Настройки; // НастройкиКомпоновкиДанных, ВыбранныеПоляКомпоновкиДанных, ОтборКомпоновкиДанных, ГруппировкаКомпоновкиДанных, ТаблицаКомпоновкиДанных, ДиаграммаКомпоновкиДанных, ЭлементУсловногоОформленияКомпоновкиДанных
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьЭлементы Тогда
		КоллекцияВложенных = ЧемЗаполнить.Элементы; // КоллекцияВыбранныхПолейКомпоновкиДанных, КоллекцияЭлементовОтбораКомпоновкиДанных
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьВыбор Тогда
		//   Выбор (ВыбранныеПоляКомпоновкиДанных).
		ЗаполнитьЗначенияСвойств(ЧтоЗаполнить.Выбор, ЧемЗаполнить.Выбор, , "ДоступныеПоляВыбора, Элементы");
		//   Выбор.Элементы (КоллекцияВыбранныхПолейКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Выбор.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.Выбор.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьОтбор Тогда
		//   Отбор (ОтборКомпоновкиДанных).
		ЗаполнитьЗначенияСвойств(ЧтоЗаполнить.Отбор, ЧемЗаполнить.Отбор, , "ДоступныеПоляОтбора, Элементы");
		//   Отбор.Элементы (КоллекцияЭлементовОтбораКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Отбор.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.Отбор.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Новый Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьПараметрыВывода Тогда
		//   ПараметрыВывода (ЗначенияПараметровВыводаКомпоновкиДанных,
		//       ЗначенияПараметровВыводаГруппировкиКомпоновкиДанных,
		//       ЗначенияПараметровВыводаГруппировкиТаблицыКомпоновкиДанных,
		//       ЗначенияПараметровВыводаГруппировкиДиаграммыКомпоновкиДанных,
		//       ЗначенияПараметровВыводаТаблицыКомпоновкиДанных,
		//       ЗначенияПараметровВыводаДиаграммыКомпоновкиДанных).
		//   ПараметрыВывода.Элементы (КоллекцияЗначенийПараметровКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.ПараметрыВывода.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			УзелВложенных = ЧтоЗаполнить.ПараметрыВывода;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				ЗначениеПараметраКД = УзелВложенных.НайтиЗначениеПараметра(ПодчиненнаяСтрока.Параметр);
				Если ЗначениеПараметраКД <> Неопределено Тогда
					ЗаполнитьЗначенияСвойств(ЗначениеПараметраКД, ПодчиненнаяСтрока);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьПараметрыДанных Тогда
		//   ПараметрыДанных (ЗначенияПараметровДанныхКомпоновкиДанных).
		//   ПараметрыДанных.Элементы (КоллекцияЗначенийПараметровКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.ПараметрыДанных.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			УзелВложенных = ЧтоЗаполнить.ПараметрыДанных;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				ЗначениеПараметраКД = УзелВложенных.НайтиЗначениеПараметра(ПодчиненнаяСтрока.Параметр);
				Если ЗначениеПараметраКД <> Неопределено Тогда
					ЗаполнитьЗначенияСвойств(ЗначениеПараметраКД, ПодчиненнаяСтрока);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьПользовательскиеПоля Тогда
		//   ПользовательскиеПоля (ПользовательскиеПоляКомпоновкиДанных).
		//   ПользовательскиеПоля.Элементы (КоллекцияПользовательскихПолейКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.ПользовательскиеПоля.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.ПользовательскиеПоля.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьПоляГруппировки Тогда
		//   ПоляГруппировки (ПоляГруппировкиКомпоновкиДанных).
		//   ПоляГруппировки.Элементы (КоллекцияПолейГруппировкиКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.ПоляГруппировки.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.ПоляГруппировки.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Новый Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьПорядок Тогда
		//   Порядок (ПорядокКомпоновкиДанных).
		ЗаполнитьЗначенияСвойств(ЧтоЗаполнить.Порядок, ЧемЗаполнить.Порядок, , "ДоступныеПоляПорядка, Элементы");
		//   Порядок.Элементы (КоллекцияЭлементовПорядкаКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Порядок.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.Порядок.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьСтруктура Тогда
		//   Структура (КоллекцияЭлементовСтруктурыНастроекКомпоновкиДанных,
		//       КоллекцияЭлементовСтруктурыДиаграммыКомпоновкиДанных,
		//       КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных).
		ЗаполнитьЗначенияСвойств(ЧтоЗаполнить.Структура, ЧемЗаполнить.Структура);
		КоллекцияВложенных = ЧемЗаполнить.Структура;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.Структура;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьУсловноеОформление Тогда
		//   УсловноеОформление (УсловноеОформлениеКомпоновкиДанных).
		ЗаполнитьЗначенияСвойств(ЧтоЗаполнить.УсловноеОформление, ЧемЗаполнить.УсловноеОформление, , "ДоступныеПоляОтбора, ДоступныеПоляПолей, Элементы");
		//   УсловноеОформление.Элементы (КоллекцияЭлементовУсловногоОформленияКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.УсловноеОформление.Элементы;
		Если КоллекцияВложенных.Количество() > 0 Тогда
			НоваяКоллекцияВложенных = ЧтоЗаполнить.УсловноеОформление.Элементы;
			Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
				СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьКолонкиИСтроки Тогда
		//   Колонки (КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Колонки;
		НоваяКоллекцияВложенных = ЧтоЗаполнить.Колонки;
		СтарыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(КоллекцияВложенных);
		НовыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(НоваяКоллекцияВложенных);
		Соответствие.Вставить(СтарыйИдентификатор, НовыйИдентификатор);
		Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
			СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
		КонецЦикла;
		//   Строки (КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Строки;
		НоваяКоллекцияВложенных = ЧтоЗаполнить.Строки;
		СтарыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(КоллекцияВложенных);
		НовыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(НоваяКоллекцияВложенных);
		Соответствие.Вставить(СтарыйИдентификатор, НовыйИдентификатор);
		Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
			СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
		КонецЦикла;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьСерииИТочки Тогда
		//   Серии (КоллекцияЭлементовСтруктурыДиаграммыКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Серии;
		НоваяКоллекцияВложенных = ЧтоЗаполнить.Серии;
		СтарыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(КоллекцияВложенных);
		НовыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(НоваяКоллекцияВложенных);
		Соответствие.Вставить(СтарыйИдентификатор, НовыйИдентификатор);
		Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
			СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
		КонецЦикла;
		//   Точки (КоллекцияЭлементовСтруктурыДиаграммыКомпоновкиДанных).
		КоллекцияВложенных = ЧемЗаполнить.Точки;
		НоваяКоллекцияВложенных = ЧтоЗаполнить.Точки;
		СтарыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(КоллекцияВложенных);
		НовыйИдентификатор = Узел.ПолучитьИдентификаторПоОбъекту(НоваяКоллекцияВложенных);
		Соответствие.Вставить(СтарыйИдентификатор, НовыйИдентификатор);
		Для Каждого ПодчиненнаяСтрока Из КоллекцияВложенных Цикл
			СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, НоваяКоллекцияВложенных, Неопределено, Соответствие);
		КонецЦикла;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьЗначенияВложенныхПараметров Тогда
		//   ЗначенияВложенныхПараметров (КоллекцияЗначенийПараметровКомпоновкиДанных).
		Для Каждого ПодчиненнаяСтрока Из ЧемЗаполнить.ЗначенияВложенныхПараметров Цикл
			СкопироватьРекурсивно(Узел, ПодчиненнаяСтрока, ЧтоЗаполнить.ЗначенияВложенныхПараметров, Неопределено, Соответствие);
		КонецЦикла;
	КонецЕсли;
	
	Если ПараметрыКопирования.ЕстьПоляИОформление Тогда
		Для Каждого ОформляемоеПоле Из ЧемЗаполнить.Поля.Элементы Цикл
			ЗаполнитьЗначенияСвойств(ЧтоЗаполнить.Поля.Элементы.Добавить(), ОформляемоеПоле);
		КонецЦикла;
		Для Каждого Источник Из ЧемЗаполнить.Оформление.Элементы Цикл
			Приемник = ЧтоЗаполнить.Оформление.НайтиЗначениеПараметра(Источник.Параметр);
			Если Приемник <> Неопределено Тогда
				ЗаполнитьЗначенияСвойств(Приемник, Источник, , "Родитель");
				Для Каждого ВложенныйИсточник Из Источник.ЗначенияВложенныхПараметров Цикл
					ВложенныйПриемник = ЧтоЗаполнить.Оформление.НайтиЗначениеПараметра(Источник.Параметр);
					Если ВложенныйПриемник <> Неопределено Тогда
						ЗаполнитьЗначенияСвойств(ВложенныйПриемник, ВложенныйИсточник, , "Родитель");
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
		
	Возврат ЧтоЗаполнить;
КонецФункции

Функция ДобавитьУникальноеЗначениеВСписок(Список, Значение, Представление, Использование) Экспорт
	Если ТипЗнч(Список) <> Тип("СписокЗначений")
		Или (Не ЗначениеЗаполнено(Значение) И Не ЗначениеЗаполнено(Представление)) Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ЭлементСписка = Список.НайтиПоЗначению(Значение);
	
	Если ЭлементСписка = Неопределено Тогда
		ЭлементСписка = Список.Добавить();
		ЭлементСписка.Значение = Значение;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Представление) Тогда
		ЭлементСписка.Представление = Представление;
	ИначеЕсли Не ЗначениеЗаполнено(ЭлементСписка.Представление) Тогда
		ЭлементСписка.Представление = Строка(Значение);
	КонецЕсли;
	
	Если Использование И Не ЭлементСписка.Пометка Тогда
		ЭлементСписка.Пометка = Истина;
	КонецЕсли;
	
	Возврат ЭлементСписка;
КонецФункции

Функция ЗначенияСписком(Значения, ТолькоЗаполненные = Ложь) Экспорт
	Если ТипЗнч(Значения) = Тип("СписокЗначений") Тогда
		Список = Значения;
	Иначе
		Список = Новый СписокЗначений;
		Если ТипЗнч(Значения) = Тип("Массив") Тогда
			Список.ЗагрузитьЗначения(Значения);
		ИначеЕсли ЗначениеЗаполнено(Значения) Тогда
			Список.Добавить(Значения);
		КонецЕсли;
	КонецЕсли;
	
	Если Не ТолькоЗаполненные Тогда 
		Возврат Список;
	КонецЕсли;
	
	Индекс = Список.Количество() - 1;
	Пока Индекс >= 0 Цикл 
		Элемент = Список[Индекс];
		Если Не ЗначениеЗаполнено(Элемент.Значение) Тогда 
			Список.Удалить(Элемент);
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;
	
	Возврат Список;
КонецФункции

Функция СтрЛевДоСимвола(Строка, Разделитель, Остаток = Неопределено)
	Позиция = СтрНайти(Строка, Разделитель);
	Если Позиция = 0 Тогда
		СтрокаДоТочки = Строка;
		Остаток = "";
	Иначе
		СтрокаДоТочки = Лев(Строка, Позиция - 1);
		Остаток = Сред(Строка, Позиция + 1);
	КонецЕсли;
	Возврат СтрокаДоТочки;
КонецФункции

Функция НайтиСтрокиТаблицы(ТаблицаРеквизит, ДанныеСтроки) Экспорт
	Если ТипЗнч(ТаблицаРеквизит) = Тип("ДанныеФормыКоллекция") Тогда // Таблица значений.
		Возврат ТаблицаРеквизит.НайтиСтроки(ДанныеСтроки);
	ИначеЕсли ТипЗнч(ТаблицаРеквизит) = Тип("ДанныеФормыДерево") Тогда // Дерево значений.
		Возврат НайтиРекурсивно(ТаблицаРеквизит.ПолучитьЭлементы(), ДанныеСтроки);
	Иначе
		Возврат Неопределено;
	КонецЕсли;
КонецФункции

Функция НайтиРекурсивно(НаборСтрок, ДанныеСтроки, Найденные = Неопределено)
	Если Найденные = Неопределено Тогда
		Найденные = Новый Массив;
	КонецЕсли;
	Для Каждого СтрокаТаблицы Из НаборСтрок Цикл
		ЗначенияСовпадают = Истина;
		Для Каждого КлючИЗначение Из ДанныеСтроки Цикл
			Если СтрокаТаблицы[КлючИЗначение.Ключ] <> КлючИЗначение.Значение Тогда
				ЗначенияСовпадают = Ложь;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		Если ЗначенияСовпадают Тогда
			Найденные.Добавить(СтрокаТаблицы);
		КонецЕсли;
		НайтиРекурсивно(СтрокаТаблицы.ПолучитьЭлементы(), ДанныеСтроки, Найденные);
	КонецЦикла;
	Возврат Найденные;
КонецФункции

Процедура ПривестиЗначениеКТипу(Значение, ОписаниеТипов) Экспорт
	Если ТипЗнч(Значение) = Тип("СписокЗначений") Тогда 
		Для Каждого ЭлементСписка Из Значение Цикл 
			Если Не ОписаниеТипов.СодержитТип(ТипЗнч(ЭлементСписка.Значение)) Тогда
				ЭлементСписка.Значение = ОписаниеТипов.ПривестиЗначение();
			КонецЕсли;
		КонецЦикла;
	Иначе
		Если Не ОписаниеТипов.СодержитТип(ТипЗнч(Значение)) Тогда
			Значение = ОписаниеТипов.ПривестиЗначение();
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

// Индекс картинки в коллекции ПиктограммыНастроекОтчета.
Функция ИндексКартинки(Тип, Состояние = Неопределено) Экспорт
	Если Тип = "Группа" Тогда
		Индекс = 1;
	ИначеЕсли Тип = "Элемент" Тогда
		Индекс = 4;
	ИначеЕсли Тип = "Группировка"
		Или Тип = "ГруппировкаТаблицы"
		Или Тип = "ГруппировкаДиаграммы" Тогда
		Индекс = 7;
	ИначеЕсли Тип = "Таблица" Тогда
		Индекс = 10;
	ИначеЕсли Тип = "Диаграмма" Тогда
		Индекс = 11;
	ИначеЕсли Тип = "НастройкиВложенногоОбъекта" Тогда
		Индекс = 12;
	ИначеЕсли Тип = "ПараметрыДанных" Тогда
		Индекс = 14;
	ИначеЕсли Тип = "ПараметрДанных" Тогда
		Индекс = 15;
	ИначеЕсли Тип = "Отборы" Тогда
		Индекс = 16;
	ИначеЕсли Тип = "ЭлементОтбора" Тогда
		Индекс = 17;
	ИначеЕсли Тип = "ВыбранныеПоля" Тогда
		Индекс = 18;
	ИначеЕсли Тип = "Сортировки" Тогда
		Индекс = 19;
	ИначеЕсли Тип = "УсловноеОформление" Тогда
		Индекс = 20;
	ИначеЕсли Тип = "Настройки" Тогда
		Индекс = 21;
	ИначеЕсли Тип = "Структура" Тогда
		Индекс = 22;
	ИначеЕсли Тип = "Ресурс" Тогда
		Индекс = 23;
	ИначеЕсли Тип = "Предупреждение" Тогда
		Индекс = 24;
	ИначеЕсли Тип = "Ошибка" Тогда
		Индекс = 25;
	Иначе
		Индекс = -2;
	КонецЕсли;
	
	Если Состояние = "ПометкаУдаления" Тогда
		Индекс = Индекс + 1;
	ИначеЕсли Состояние = "Предопределенный" Тогда
		Индекс = Индекс + 2;
	КонецЕсли;
	
	Возврат Индекс;
КонецФункции

Функция КлючУникальности(ПолноеИмяОтчета, КлючВарианта) Экспорт
	Результат = ПолноеИмяОтчета;
	Если ЗначениеЗаполнено(КлючВарианта) Тогда
		Результат = Результат + "/КлючВарианта." + КлючВарианта;
	КонецЕсли;
	Возврат Результат;
КонецФункции

Функция УсловиеЭлементаНастройки(Элемент, Описание) Экспорт 
	Условие = ВидСравненияКомпоновкиДанных.Равно;
	
	Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда 
		Условие = Элемент.ВидСравнения;
	ИначеЕсли ТипЗнч(Элемент) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных")
		И Описание.ДоступенСписокЗначений Тогда 
		Условие = ВидСравненияКомпоновкиДанных.ВСписке;
	КонецЕсли;
	
	Возврат Условие;
КонецФункции

Функция ЭтоВидСравненияСписка(ВидСравнения) Экспорт 
	ВидыСравнений = Новый Массив;
	ВидыСравнений.Добавить(ВидСравненияКомпоновкиДанных.ВСписке);
	ВидыСравнений.Добавить(ВидСравненияКомпоновкиДанных.НеВСписке);
	ВидыСравнений.Добавить(ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии);
	ВидыСравнений.Добавить(ВидСравненияКомпоновкиДанных.НеВСпискеПоИерархии);
	
	Возврат ВидыСравнений.Найти(ВидСравнения) <> Неопределено;
КонецФункции

Функция ПараметрыВыбора(Настройки, ПользовательскиеНастройки, ЭлементНастройки, РежимИзмененияВарианта = Ложь) Экспорт 
	ПараметрыВыбора = Новый Массив;
	
	ОписаниеЭлементаНастройки = НайтиДоступнуюНастройку(Настройки, ЭлементНастройки);
	Если ОписаниеЭлементаНастройки = Неопределено Тогда 
		Возврат Новый ФиксированныйМассив(ПараметрыВыбора);
	КонецЕсли;
	
	Параметры = ОписаниеЭлементаНастройки.ПолучитьПараметрыВыбора(); // ПараметрыВыбораКомпоновкиДанных
	Для Каждого Параметр Из Параметры Цикл 
		Если ЗначениеЗаполнено(Параметр.Имя) Тогда
			ПараметрыВыбора.Добавить(Новый ПараметрВыбора(Параметр.Имя, Параметр.Значение));
		КонецЕсли;
	КонецЦикла;
	
	Параметры = ОписаниеЭлементаНастройки.ПолучитьСвязиПараметровВыбора(); // СвязиПараметровВыбораКомпоновкиДанных
	Для Каждого Параметр Из Параметры Цикл 
		Если Не ЗначениеЗаполнено(Параметр.Имя) Тогда
			Продолжить;
		КонецЕсли;
		
		Значение = ЗначениеПараметраВыбора(Настройки, ПользовательскиеНастройки, Параметр.Поле, РежимИзмененияВарианта);
		Если ЗначениеЗаполнено(Значение) Тогда 
			ПараметрыВыбора.Добавить(Новый ПараметрВыбора(Параметр.Имя, Значение));
		КонецЕсли;
	КонецЦикла;
	
	Возврат Новый ФиксированныйМассив(ПараметрыВыбора);
КонецФункции

Функция ИмяСобытияНастройкиПоУмолчанию() Экспорт 
	
	Возврат "НастройкиПоУмолчанию";
	
КонецФункции

#КонецОбласти
